package com.sisgesbyte.web.managedBean.proyeccion;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import com.sisgesbyte.common.ConstantesInternasSistema;
import com.sisgesbyte.dao.beanDao.FiltrosBean;
import com.sisgesbyte.dao.beanDao.FiltrosSQLBean;
import com.sisgesbyte.services.administracion.MantenimientoCategoriaCliente;
import com.sisgesbyte.services.administracion.MantenimientoCategoriaProd;
import com.sisgesbyte.services.administracion.bean.CategoriaClienteBean;
import com.sisgesbyte.services.administracion.bean.CategoriaClienteListaRes;
import com.sisgesbyte.services.administracion.bean.CategoriaProdBean;
import com.sisgesbyte.services.administracion.bean.CategoriaProdListaResponse;
import com.sisgesbyte.services.administracion.bean.ZonaBean;
import com.sisgesbyte.services.proyeccion.ProyeccionFfVvService;
import com.sisgesbyte.services.proyeccion.bean.AvanceProyeccionFFVVResponse;
import com.sisgesbyte.services.proyeccion.bean.AvanceProyeccionProductResponse;
import com.sisgesbyte.services.proyeccion.bean.AvanceVentaProductosBean;
import com.sisgesbyte.services.proyeccion.bean.FiltroOpcionesFFVVBean;
import com.sisgesbyte.services.proyeccion.bean.ProyeccionFFVVBean;
import com.sisgesbyte.services.ventas.MantenimientoPeriodo;
import com.sisgesbyte.services.ventas.MantenimientoZona;
import com.sisgesbyte.services.ventas.bean.PeriodoBean;
import com.sisgesbyte.services.ventas.bean.PeriodoListaBean;
import com.sisgesbyte.services.ventas.bean.ZonaListaResponse;

@ManagedBean
@ViewScoped
public class ProyeccionFfvvMBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@EJB
	private ProyeccionFfVvService proyeccionFfVvService;
	@EJB
	private MantenimientoPeriodo mantenimientoPeriodo;
	@EJB
	private MantenimientoZona mantenimientoZona;
	@EJB
	private MantenimientoCategoriaCliente mantenimientoCategoriaCliente;
	@EJB
	private MantenimientoCategoriaProd mantenimientoCategoriaProd;

	private List<CategoriaClienteBean> listaCanales;
	private Integer periodoDefault;
	private List<PeriodoBean> listaPeriodos;
	private List<ZonaBean> listaZonas;
	private int idZona;
	private int idCanal;
	// variables para proyeccion productos
	private List<AvanceVentaProductosBean> listaProductosFfvv;
	private List<CategoriaProdBean> listaCategoriaProductos;
	private List<CategoriaProdBean> listaCategoriaProductosPadres;
	private List<CategoriaProdBean> listaCategoriaProductosHijos;
	private String txtBuscar;
	private int idCategoriaProducto;
	private List<AvanceVentaProductosBean> listaProductos;
	private List<AvanceVentaProductosBean> listaProductosTemporal;
	private List<CategoriaProdBean> categoriaHijos;
	// -------
	private TreeNode selectedNode;
	private TreeNode root;
	private TreeNode[] node;
	private List<ProyeccionFFVVBean> listaCategoriaPadres;
	private List<ProyeccionFFVVBean> listaCategoriaHijos;
	private Map<Integer, Integer> auxNumNode;
	private ProyeccionFFVVBean selectedFFVV;
	private int numNode;
	private Boolean bloquear;

	@PostConstruct
	public void init() {

		setBloquear(true);
		cargarPeriodos();
		mostrarPeriodoDefault();
		cargarZonas();
		cargarCanales();
		auxNumNode = new HashMap<Integer, Integer>();
		inicializar();
		txtBuscar = "";
		cargarCategorias();
		categoriaHijos = new ArrayList<CategoriaProdBean>();
	}

	public void inicializar() {
		try {
			setBloquear(true);
			numNode = 0;
			root = new DefaultTreeNode("Root", null);
			FiltroOpcionesFFVVBean filtros = new FiltroOpcionesFFVVBean();
			filtros.setIdPeriodo(periodoDefault);
			filtros.setIdZona(idZona);
			filtros.setIdCanal(idCanal);
			AvanceProyeccionFFVVResponse avance = proyeccionFfVvService
					.avanceProyeccionFFVV(ObtenerIdTransaccion(), filtros);
			listaCategoriaPadres = new ArrayList<ProyeccionFFVVBean>();
			listaCategoriaHijos = new ArrayList<ProyeccionFFVVBean>();
			// capturamos las id de la estructura de ventas
			List<Integer> idEstructura = new ArrayList<Integer>();
			int idPadre = 0;
			for (ProyeccionFFVVBean lista : avance.getListaAvanceFFVV()) {
				if (!idEstructura.contains(lista.getIdEstructura())) {
					idEstructura.add(lista.getIdEstructura());
				}
			}
			// ordenamos de menor a mayor la estructura de venta obtenida
			Collections.sort(idEstructura);

			// capturamos la menor y ese seria el padre
			idPadre = idEstructura.get(0);

			for (ProyeccionFFVVBean ls : avance.getListaAvanceFFVV()) {

				// seleccionamos a la FFVV que tiene la misma estructura(es
				// decir gerentes o supervisores)
				if (ls.getIdEstructura() == idPadre) {
					listaCategoriaPadres.add(ls);
				} else {
					listaCategoriaHijos.add(ls);
				}

			}

			int max = avance.getListaAvanceFFVV().size();
			if (max > 0) {
				node = new TreeNode[max];
				for (ProyeccionFFVVBean ls : listaCategoriaPadres) {
					node[numNode] = new DefaultTreeNode(ls, root);
					auxNumNode.put(ls.getIdFFVV(), numNode);
					numNode++;
					assignChildren(ls);
				}
			}

		} catch (Exception e) {
			System.out
					.println("Hubo un error en servicio ProyeccionFfVvService ");
		}
	}

	public void buscarProductosAvance() {
		try {
			FiltroOpcionesFFVVBean filtros = new FiltroOpcionesFFVVBean();
			
			filtros.setIdFfvv(selectedFFVV.getIdFFVV());
			filtros.setIdPeriodo(periodoDefault);

			AvanceProyeccionProductResponse listaProductosZona = proyeccionFfVvService
					.avanceProductosFFVV(ObtenerIdTransaccion(), filtros);
			this.listaProductos = new ArrayList<AvanceVentaProductosBean>();

			if (listaProductosZona.getCodigoRespuesta().equalsIgnoreCase(
					ConstantesInternasSistema.CODIGO_EXITO)) {
				this.listaProductos = listaProductosZona
						.getListaProductosZonas();
				// variable temporal para los productos y poder aplicarles
				// filtro
				this.listaProductosTemporal = this.listaProductos;
			} else {
				System.out.println("Error al obtener los productos");
			}
		} catch (Exception e) {
			System.out
					.println("Error al obtener la lista de productos por zona "
							+ e.getMessage());
		}
	}

	public void cargarPeriodos() {
		try {
			PeriodoListaBean periodos = mantenimientoPeriodo
					.listaPeriodos(ObtenerIdTransaccion());
			this.listaPeriodos = periodos.getListaPeriodos();
		} catch (Exception e) {
			System.out.println("Error al cargar los periodos: " + e);
		}
	}

	public void mostrarPeriodoDefault() {
		for (PeriodoBean ls : getListaPeriodos()) {
			if (ls.getDefecto() != null && ls.getDefecto() == true) {
				setPeriodoDefault(ls.getId());
			}
		}
	}

	public void cargarZonas() {
		try {
			FiltrosSQLBean filtro = new FiltrosSQLBean();
			List<FiltrosBean> listaFiltros = new ArrayList<FiltrosBean>();
			FiltrosBean filtroCampos = new FiltrosBean();
			List<String> campos = new ArrayList<String>();
			campos.add("active");
			filtroCampos.setCampos(campos);
			filtroCampos.setOperador("=");
			listaFiltros.add(filtroCampos);
			List<Object> valores = new ArrayList<Object>();
			valores.add(true);
			filtro.setListaFiltros(listaFiltros);
			filtro.setListaValores(valores);
			ZonaListaResponse zonas = mantenimientoZona.listaZonas(
					ObtenerIdTransaccion(), filtro);
			if (zonas.getCodigoRespuesta().equalsIgnoreCase(
					ConstantesInternasSistema.CODIGO_EXITO)) {
				this.listaZonas = zonas.getListaZonas();
			}

		} catch (Exception e) {
			System.out.println("Error al obtener las zonas: " + e);
		}
	}

	public void cargarCanales() {
		try {
			FiltrosSQLBean filtro = new FiltrosSQLBean();
			List<FiltrosBean> listaFiltros = new ArrayList<FiltrosBean>();
			FiltrosBean filtroCampos = new FiltrosBean();
			List<String> campos = new ArrayList<String>();
			campos.add("active");
			filtroCampos.setCampos(campos);
			filtroCampos.setOperador("=");
			listaFiltros.add(filtroCampos);
			List<Object> valores = new ArrayList<Object>();
			valores.add(true);
			filtro.setListaFiltros(listaFiltros);
			filtro.setListaValores(valores);
			CategoriaClienteListaRes canales = mantenimientoCategoriaCliente
					.listaCategoriaCliente(ObtenerIdTransaccion(), filtro);
			if (canales.getCodigoRespuesta().equalsIgnoreCase(
					ConstantesInternasSistema.CODIGO_EXITO)) {
				this.listaCanales = canales.getListaCategoriaCliente();
			}

		} catch (Exception e) {
			System.out.println("Error al obtener los canales: " + e);
		}
	}
	
	public String ObtenerIdTransaccion() {
		String sessionId = "";
		try {
			FacesContext fCtx = FacesContext.getCurrentInstance();
			HttpSession session = (HttpSession) fCtx.getExternalContext()
					.getSession(false);
			sessionId = session.getId().replace(".undefined", "");
		} catch (Exception e) {
			sessionId = "Error";
			System.out.println("Error al obtener Session" + e);
		}
		return sessionId;
	}

	/**
	 * Establece los nodos hijos a un árbol menu de forma recursiva.
	 * 
	 * @param father
	 *            El nodo padre.
	 */
	private void assignChildren(ProyeccionFFVVBean father) {
		List<ProyeccionFFVVBean> children = new ArrayList<ProyeccionFFVVBean>();
		children = getMenuByFather(father);
		Iterator<ProyeccionFFVVBean> iter = children.iterator();

		while (iter.hasNext()) {
			ProyeccionFFVVBean child = iter.next();
			node[numNode] = new DefaultTreeNode("document", child,
					node[auxNumNode.get(father.getIdFFVV())]);
			auxNumNode.put(child.getIdFFVV(), numNode);
			numNode++;
			assignChildren(child);
		}
	}

	/**
	 * Devuelve una lista de nodos según su padre.
	 * 
	 * @param father
	 *            El nodo padre.
	 * @return La lista de nodos.
	 */
	private List<ProyeccionFFVVBean> getMenuByFather(ProyeccionFFVVBean father) {

		List<ProyeccionFFVVBean> listR = new ArrayList<ProyeccionFFVVBean>();
		Iterator<ProyeccionFFVVBean> it = listaCategoriaHijos.iterator();
		while (it.hasNext()) {
			ProyeccionFFVVBean me = it.next();
			if (me.getIdPadre().intValue() == father.getIdFFVV()) {
				listR.add(me);
				it.remove();
			}
		}
		return listR;
	}

	public void onNodeSelect(NodeSelectEvent event) {
		setBloquear(false);
		ProyeccionFFVVBean selected = (ProyeccionFFVVBean) event.getTreeNode().getData();
		this.selectedFFVV = selected;
		buscarProductosAvance();
	}

	public void cargarCategorias() {
		try {

			CategoriaProdListaResponse categorias = mantenimientoCategoriaProd
					.listaCategoriasProducto(ObtenerIdTransaccion(), null);
			listaCategoriaProductos = new ArrayList<CategoriaProdBean>();
			listaCategoriaProductosPadres = new ArrayList<CategoriaProdBean>();
			listaCategoriaProductosHijos = new ArrayList<CategoriaProdBean>();
			for (CategoriaProdBean ls : categorias.getListaCategoriaProductos()) {
				if (ls.getPadre_id() == 0) {
					listaCategoriaProductosPadres.add(ls);
				} else {
					listaCategoriaProductosHijos.add(ls);
				}
			}

			for (CategoriaProdBean ls : listaCategoriaProductosPadres) {
				listaCategoriaProductos.add(ls);
				mostrarHijos(ls.getId());
			}
		} catch (Exception e) {
			System.out.println("Error al cargar las categorias: " + e);
		}
	}

	// metodo para obtener la estructura de hijos de una categoria
	public void mostrarHijos(int padreId) {

		for (CategoriaProdBean ls : listaCategoriaProductosHijos) {
			if (padreId == ls.getPadre_id()) {
				listaCategoriaProductos.add(ls);
				mostrarHijos(ls.getId());
			}
		}
	}

	public void obtenerCategoriaHijos(int idPadre) {

		for (CategoriaProdBean ls : listaCategoriaProductos) {
			if (idPadre == ls.getPadre_id()) {
				categoriaHijos.add(ls);
				obtenerCategoriaHijos(ls.getId());
			}
		}
	}

	public void crearFiltro() {
		categoriaHijos = new ArrayList<CategoriaProdBean>();
		this.listaProductosTemporal = new ArrayList<AvanceVentaProductosBean>();

		// buscamos al padre
		for (CategoriaProdBean ls : listaCategoriaProductos) {
			if (idCategoriaProducto == ls.getId()) {
				categoriaHijos.add(ls);
			}
		}
		// buscamos los hijos
		obtenerCategoriaHijos(idCategoriaProducto);

		// recorremos las categorias
		for (CategoriaProdBean cat : categoriaHijos) {
			// buscamos los productos por categoria
			for (AvanceVentaProductosBean prod : listaProductos) {
				if (prod.getCategoriaProductoId() == cat.getId()
						&& (prod.getMarca() + " / " + prod.getProducto()
								+ " / " + prod.getCodProd()).toLowerCase()
								.contains(txtBuscar.toLowerCase().trim())) {
					this.listaProductosTemporal.add(prod);
				}
			}
		}
	}

	public Integer getPeriodoDefault() {
		return periodoDefault;
	}

	public void setPeriodoDefault(Integer periodoDefault) {
		this.periodoDefault = periodoDefault;
	}

	public List<PeriodoBean> getListaPeriodos() {
		return listaPeriodos;
	}

	public void setListaPeriodos(List<PeriodoBean> listaPeriodos) {
		this.listaPeriodos = listaPeriodos;
	}

	public List<ZonaBean> getListaZonas() {
		return listaZonas;
	}

	public void setListaZonas(List<ZonaBean> listaZonas) {
		this.listaZonas = listaZonas;
	}

	public int getIdZona() {
		return idZona;
	}

	public void setIdZona(int idZona) {
		this.idZona = idZona;
	}

	public List<CategoriaClienteBean> getListaCanales() {
		return listaCanales;
	}

	public void setListaCanales(List<CategoriaClienteBean> listaCanales) {
		this.listaCanales = listaCanales;
	}

	public int getIdCanal() {
		return idCanal;
	}

	public void setIdCanal(int idCanal) {
		this.idCanal = idCanal;
	}

	public TreeNode getSelectedNode() {
		return selectedNode;
	}

	public void setSelectedNode(TreeNode selectedNode) {
		this.selectedNode = selectedNode;
	}

	public TreeNode getRoot() {
		return root;
	}

	public void setRoot(TreeNode root) {
		this.root = root;
	}

	public Boolean getBloquear() {
		return bloquear;
	}

	public void setBloquear(Boolean bloquear) {
		this.bloquear = bloquear;
	}

	public ProyeccionFFVVBean getSelectedFFVV() {
		return selectedFFVV;
	}

	public void setSelectedFFVV(ProyeccionFFVVBean selectedFFVV) {
		this.selectedFFVV = selectedFFVV;
	}

	public List<AvanceVentaProductosBean> getListaProductosFfvv() {
		return listaProductosFfvv;
	}

	public void setListaProductosFfvv(
			List<AvanceVentaProductosBean> listaProductosFfvv) {
		this.listaProductosFfvv = listaProductosFfvv;
	}

	public List<CategoriaProdBean> getListaCategoriaProductos() {
		return listaCategoriaProductos;
	}

	public void setListaCategoriaProductos(
			List<CategoriaProdBean> listaCategoriaProductos) {
		this.listaCategoriaProductos = listaCategoriaProductos;
	}

	public int getIdCategoriaProducto() {
		return idCategoriaProducto;
	}

	public void setIdCategoriaProducto(int idCategoriaProducto) {
		this.idCategoriaProducto = idCategoriaProducto;
	}

	public List<AvanceVentaProductosBean> getListaProductos() {
		return listaProductos;
	}

	public void setListaProductos(List<AvanceVentaProductosBean> listaProductos) {
		this.listaProductos = listaProductos;
	}

	public List<AvanceVentaProductosBean> getListaProductosTemporal() {
		return listaProductosTemporal;
	}

	public void setListaProductosTemporal(
			List<AvanceVentaProductosBean> listaProductosTemporal) {
		this.listaProductosTemporal = listaProductosTemporal;
	}

	public String getTxtBuscar() {
		return txtBuscar;
	}

	public void setTxtBuscar(String txtBuscar) {
		this.txtBuscar = txtBuscar;
	}

}
